package cn.edu.jsu.zjj.service.impl;

import cn.edu.jsu.zjj.common.result.Result;
import cn.edu.jsu.zjj.constant.MessageConstant;
import cn.edu.jsu.zjj.exception.BaseException;
import cn.edu.jsu.zjj.mapper.DocuMapper;
import cn.edu.jsu.zjj.mapper.SysDataMapper;
import cn.edu.jsu.zjj.mapper.SysHeaderMapper;
import cn.edu.jsu.zjj.mapper.UserMapper;
import cn.edu.jsu.zjj.model.dto.docu.DocuQueryRequest;
import cn.edu.jsu.zjj.model.entity.Docu;
import cn.edu.jsu.zjj.model.entity.SysData;
import cn.edu.jsu.zjj.model.entity.SysHeader;
import cn.edu.jsu.zjj.model.utils.ExcelUtils;
import cn.edu.jsu.zjj.model.utils.ZipUtils;
import cn.edu.jsu.zjj.model.vo.ZipVo;
import cn.edu.jsu.zjj.service.DocuService;
import cn.edu.jsu.zjj.service.ISysDataService;
import cn.edu.jsu.zjj.service.ISysHeaderService;
import cn.edu.jsu.zjj.service.UserService;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.zhxu.bs.BeanSearcher;
import cn.zhxu.bs.util.MapUtils;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import kotlin.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据表 服务实现类
 * </p>
 *
 * @author fyt
 * @since 2024-06-12
 */
@Service
public class SysDataServiceImpl extends ServiceImpl<SysDataMapper, SysData> implements ISysDataService {
    @Autowired
    private ISysHeaderService headerService;
    @Autowired
    private ISysDataService dataService;
    @Autowired
    private BeanSearcher beanSearcher;
    @Autowired
    private UserService userService;
    @Autowired
    private SysDataMapper dataMapper;
    @Autowired
    private DocuService docuService;

    /**
     * 导出Excel-动态头写入
     *
     * @param id 资料id
     */
    public void dynamicHeadExport(Long id, HttpServletResponse response) throws IOException {
        // 设置动态头
        List<SysHeader> headers = headerService.list(new LambdaQueryWrapper<SysHeader>().eq(SysHeader::getDocuId, id).select(SysHeader::getName));
        List<List<String>> headList = new ArrayList<>();
        for (SysHeader header : headers) {
            ArrayList<String> arrayList = new ArrayList<>();
            arrayList.add(header.getName());
            headList.add(arrayList);
        }
        List<List<Object>> dataList = new ArrayList<>();
        // 获取动态数据
        List<SysData> sysDataList = dataService.list(new LambdaQueryWrapper<SysData>().eq(SysData::getDocuId, id));

        for (SysData sysData : sysDataList) {
            JSONObject jsonObject = JSONUtil.parseObj(sysData.getData());
            List<Object> objectList = new ArrayList<>();
            for (Map.Entry<String, Object> entry : jsonObject) {
                objectList.add(entry.getValue());
            }
            dataList.add(objectList);
        }


        // 写入数据
        ExcelUtils.export(response, headList, dataList,null);
    }



    @Override
    public List<SysData> shit(Long docuId, String headersJSON) {
        Map<String, String> headers = JSONUtil.toBean(headersJSON, HashMap.class);
        return dataMapper.shit(docuId, headers);
    }

    @Override
    public void exportMulti(DocuQueryRequest docuQueryRequest, HttpServletResponse response) {
        // 获取表头,判断是否相同
        List<Long> ids = docuQueryRequest.getIds();
        List<SysHeader> headers = headerService.list(new LambdaQueryWrapper<SysHeader>().in(SysHeader::getDocuId, ids).ne(SysHeader::getIsDelete, 1));
        List<SysData> dataList = dataMapper.selectList(new LambdaQueryWrapper<SysData>().in(SysData::getDocuId, ids).ne(SysData::getIsDelete, 1));
        List<List<Object>> dataLists = new ArrayList<>();
        List<String> fileNameList = new ArrayList<>();
        List<byte[]> bytesList = new ArrayList<>();

        // 获取去重的表头
        List<String> newHeaderList = headers.stream().map(SysHeader::getName).distinct().collect(Collectors.toList());

        int size = headers.size() / 2;
        //表头不一致
        if (newHeaderList.size() != size) {
            export(docuQueryRequest, ids, response);
        }

        //表头一致，遍历表头，添加到headerList中
        //构建表头
        List<String> headerList = new ArrayList<>(newHeaderList);
        headerList.add("附件");

        // 遍历数据，添加到dataLists中
        for (SysData data : dataList) {
            JSONObject jsonObject = JSONUtil.parseObj(data.getData());
            List<Object> dataInfo = new ArrayList<>();
            for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                dataInfo.add(entry.getValue());
            }
            // 附件
            String fileUrl = data.getFileUrl();
            if (StringUtils.isNotEmpty(fileUrl)) {
                ZipUtils.urlToByte(data.getFileUrl());
                fileNameList.add(ZipUtils.fileName);
                bytesList.add(ZipUtils.urlBytes);
            }
            dataInfo.add(data.getFileName());
            dataLists.add(dataInfo);
        }


        // Remove duplicates and keep track of removed items
        Set<List<Object>> seen = new HashSet<>();
        //去掉的数据
        List<List<Object>> removedDataList = new ArrayList<>();
        // 去掉重复数据
        List<List<Object>> uniqueDataList = new ArrayList<>();

        for (List<Object> dataInfo : dataLists) {
            if (!seen.add(dataInfo)) {
                removedDataList.add(dataInfo);
            } else {
                uniqueDataList.add(dataInfo);
            }
        }

        // Export the unique data list
        try {
            Pair<List<String>, List<byte[]>> pair = new Pair<>(fileNameList, bytesList);
            ZipUtils.main(response, headerList, uniqueDataList,pair,"测试",removedDataList);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //表头搜索不一致
        public void export(DocuQueryRequest docuQueryRequest, List<Long> ids, HttpServletResponse response) {
        long page = docuQueryRequest.getCurrent() - 1;
        int size = docuQueryRequest.getPageSize();
        List<ZipVo> zipVoList = new ArrayList<>();
        List<Docu> docuList = new ArrayList<>();

        if (ids.isEmpty()) {
            docuList = beanSearcher.search(Docu.class,
                    MapUtils.builder()
                            .field(Docu::getName, docuQueryRequest.getName()).op("ct")
                            .field(Docu::getOperName, docuQueryRequest.getOperName()).op("ct")
                            .field(Docu::getIsDelete, 0)
                            .field(Docu::getCreateTime, docuQueryRequest.getCreateTime()).op("ge")
                            .field(Docu::getEndTime, docuQueryRequest.getEndTime()).op("le")
                            .field(Docu::getStatus, docuQueryRequest.getStatus())
                            .field(Docu::getTerm, docuQueryRequest.getTerm())
                            .page(page, size)
                            .orderBy("createTime", "desc") // 使用 orderBy 方法按创建时间降序排序
                            .build()).getDataList();
        } else {
            docuList = docuService.list(new LambdaQueryWrapper<Docu>()
                    .in(Docu::getId, ids)
                    .ne(Docu::getIsDelete, 1));
        }

        // 判断是否过期
        for (Docu docu : docuList) {
            if (docu.getEndTime().before(Date.from(LocalDate.now().plusDays(1).atStartOfDay().toInstant(ZoneOffset.of("+8"))))) {
                docu.setStatus("0");
                docuService.updateById(docu);
            }
        }

        // 获取ID列表
        List<Long> docuIds = docuList.stream().map(Docu::getId).collect(Collectors.toList());

        if (docuIds.isEmpty()) {
            throw new BaseException(MessageConstant.DATA_NULL);
        }
        for (Long id : docuIds) {
            List<SysHeader> headers = headerService.list(new LambdaQueryWrapper<SysHeader>()
                    .eq(SysHeader::getDocuId, id)
                    .orderByAsc(SysHeader::getSort));
            List<String> headList = new ArrayList<>();
            List<String> sortList = new ArrayList<>();
            for (SysHeader header : headers) {
                headList.add(header.getName());
                sortList.add(header.getHeaderKey());
            }
            // 添加附件列
            headList.add("附件名称");
            List<List<Object>> dataList = new ArrayList<>();

            List<String> userRoleList = userService.getLoginUser().getRoles();

            // 获取动态数据
            LambdaQueryWrapper<SysData> queryWrapper1 = new LambdaQueryWrapper<SysData>()
                    .eq(SysData::getDocuId, id)
                    .ne(SysData::getIsDelete, 1);
            // 教师角色，只能查看自己的资料
            if (userRoleList.contains("user")) {
                queryWrapper1.eq(SysData::getUserId, userService.getLoginUser().getId());
            }
            List<SysData> sysDataList = dataMapper.selectList(queryWrapper1);

            // 文件名，二进制数组的键值对
            List<String> fileNameList = new ArrayList<>();
            List<byte[]> bytesList = new ArrayList<>();

            for (SysData sysData : sysDataList) {
                JSONObject jsonObject = JSONUtil.parseObj(sysData.getData());
                List<Object> objectList = new ArrayList<>();

                for (String sort : sortList) {
                    boolean found = false;
                    for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                        if (Objects.equals(entry.getKey(), sort)) {
                            objectList.add(entry.getValue());
                            found = true;
                            break; // 找到后跳出内层循环
                        }
                    }
                    if (!found) {
                        objectList.add(null); // 如果没有找到对应的 key，添加 null
                    }
                }

                objectList.add(sysData.getFileName());
                dataList.add(objectList);

                // 附件
                String fileUrl = sysData.getFileUrl();
                if (StringUtils.isNotEmpty(fileUrl)) {
                    ZipUtils.urlToByte(sysData.getFileUrl());
                    fileNameList.add(ZipUtils.fileName);
                    bytesList.add(ZipUtils.urlBytes);
                }
            }

            // 将文件名和二进制数组的键值对封装成Pair对象
            Pair<List<String>, List<byte[]>> pair = new Pair<>(fileNameList, bytesList);

            LambdaQueryWrapper<Docu> docuQueryWrapper = new LambdaQueryWrapper<>();
            docuQueryWrapper.eq(Docu::getId, id);
            Docu docu = docuService.getOne(docuQueryWrapper);
            String excelName = docu.getName();
            // 调用工具类进行导出
            if (headList == null || dataList == null || dataList.isEmpty() || headList.isEmpty()) {
                continue; // 跳过当前循环
            }

            ZipVo zipVo = new ZipVo();
            zipVo.setHeaders(headList);
            zipVo.setData(dataList);
            zipVo.setPair(pair);
            zipVo.setExcelName(excelName);
            zipVoList.add(zipVo);

        }

        try {
            ZipUtils.totalMain(response, zipVoList);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
